﻿//-----------------------------------------------------------------------
// <copyright file="ThreadedManager.cs" company="FastNET Services">
//     Copyright (c) 2007-2009. All Rights Reserved.
// </copyright>
// <license>
//     GPLv2
// </license>
// <warranty>
//     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
//     BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
//     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
//     DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//     OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// </warranty>
//-----------------------------------------------------------------------
#region Usings
using System;
using System.Threading;
using FastNET.CleanAct.Client.Interfaces.Managers;

#endregion

namespace FastNET.CleanAct.Client.ClientEngine.Managers
{
    /// <summary>
    /// Base class for all threaded managers
    /// </summary>
    internal abstract class ThreadedManager : IThreadedManager
    {
        #region Variables

        private readonly ManualResetEvent _threadPause;
        private Thread _managerThread;

        #endregion

        #region CTor/DTor

        /// <summary>
        /// Initializes a new instance of the ThreadedManager class
        /// </summary>
        protected ThreadedManager()
        {
            _threadPause = new ManualResetEvent(true);
        }

        #endregion

        #region Public Properties

        /// <summary>
        /// Gets a value indicating whether or not the manager status shows it is running
        /// </summary>
        public bool IsAlive
        {
            get
            {
                return _managerThread != null && _managerThread.IsAlive;
            }
        }

        #endregion

        #region Protected Abstract Properties

        /// <summary>
        /// Gets the name for the background management thread
        /// </summary>
        protected abstract string ThreadName { get; }

        /// <summary>
        /// Gets the priority for the background management thread
        /// </summary>
        protected abstract ThreadPriority ThreadPriority { get; }

        #endregion

        #region Public Main Thread Management

        /// <summary>
        /// Starts the manager background thread
        /// </summary>
        public void Start()
        {
            if (IsAlive)
            {
                throw new InvalidOperationException("Stop must be called before restarting");
            }

            _managerThread = new Thread(ManagerThread)
            {
                Name = ThreadName,
                Priority = ThreadPriority
            };

            _managerThread.Start();
        }

        /// <summary>
        /// Stops the manager background thread
        /// </summary>
        public void Stop()
        {
            if (IsAlive)
            {
                _managerThread.Abort();
                _managerThread.Join(60000);
            }

            _managerThread = null;
        }

        /// <summary>
        /// Pauses the next cycle for the background thread
        /// </summary>
        public void Pause()
        {
            _threadPause.Reset();
        }

        /// <summary>
        /// Resumes the next cycle for the background thread
        /// </summary>
        public void Resume()
        {
            _threadPause.Set();
        }

        #endregion

        #region Protected Abstract Methods

        /// <summary>
        /// Background thread cycle method
        /// </summary>
        protected abstract void ProcessThreadTasks();

        #endregion

        #region Private Methods

        /// <summary>
        /// Background manager thread for session manager
        /// </summary>
        private void ManagerThread()
        {
            // Catch thread aborting
            try
            {
                while (true)
                {
                    // This is used for pausing the process
                    _threadPause.WaitOne();

                    ProcessThreadTasks();

                    Thread.Sleep(100);
                }
            }
            catch (ThreadAbortException)
            {

            }
        }

        #endregion
    }
}
